package cn.com.cfae.iras.doc.analyze.mq.consumer;

import cn.com.cfae.iras.doc.analyze.beans.iaad.IaadAnalyzeJob;
import cn.com.cfae.iras.doc.analyze.beans.iaad.IaadAnalyzeJobDetail;
import cn.com.cfae.iras.doc.analyze.beans.iaad.IaadGrade;
import cn.com.cfae.iras.doc.analyze.beans.iaad.IaadIndicatorGradeDetail;
import cn.com.cfae.iras.doc.analyze.beans.iaad.IndustryIndicatorList;
import cn.com.cfae.iras.doc.analyze.config.ApplicationContextHelper;
import cn.com.cfae.iras.doc.analyze.parse.PdfParser;
import cn.com.cfae.iras.doc.analyze.parse.kv.KVText;
import cn.com.cfae.iras.doc.analyze.parse.model.ChapterModel;
import cn.com.cfae.iras.doc.analyze.parse.model.DocumentModel;
import cn.com.cfae.iras.doc.analyze.parse.model.ExtractBizModel;
import cn.com.cfae.iras.doc.analyze.parse.model.ExtractItem;
import cn.com.cfae.iras.doc.analyze.parse.model.IndustryType;
import cn.com.cfae.iras.doc.analyze.parse.model.TableType;
import cn.com.cfae.iras.doc.analyze.service.integrityregulation.IntegrityRegulationService;
import com.alibaba.fastjson.JSONObject;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import org.apache.rocketmq.client.producer.DefaultMQProducer;
import org.apache.rocketmq.client.producer.SendCallback;
import org.apache.rocketmq.client.producer.SendResult;
import org.apache.rocketmq.common.message.Message;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.lang.reflect.Method;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Created by 佟媛媛 on 18/10/23.
 * 指标抽取
 */

@Component
public class DocAnalyzeIaadConsumer {

    private static Logger log = LoggerFactory.getLogger(DocAnalyzeIaadConsumer.class);

    @Value("${doc.analyze.save.path}")
    private String docAnalyzeSavePath;
    @Value("${rocketmq.topic.analyze_status}")
    private String topicAnalyzeStatus;
    @Autowired
    @Qualifier("analyzeStatusProducer")
    private DefaultMQProducer analyzeStatusProducer;
    @Autowired
    private IntegrityRegulationService integrityRegulationService;

    public JSONObject handleMessage(String topic, String tag, String messageBody) throws Exception{
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
        String startTime = df.format(new Date());
        JSONObject returnMsg = new JSONObject();
        long t1 = System.currentTimeMillis();
        StringBuffer msg = new StringBuffer();
        int code = 0;
        if (StringUtils.isEmpty(messageBody)) {
            log.error("消息为空");
            code = -1004;
            msg.append("参数type错误");
        }else{
            JSONObject receiveMsg = JSONObject.parseObject(messageBody);
            String documentId = receiveMsg.getString("documentId");
            String jobId = receiveMsg.getString("jobId");
            String pdfPath = receiveMsg.getString("pdfPath");
            String industryType = receiveMsg.getString("industryType");
            File pdfFile = new File(pdfPath);
            if (pdfFile.exists()) {
                IndustryType _industryType = getIndustryType(industryType);
                if(_industryType!=null){
                    DocumentModel documentModel = analyze(pdfFile,_industryType,documentId);
                    if(documentModel!=null){
                        Class clazz = null;
                        String component = _industryType+industryType;
                        String path = "cn.com.cfae.iras.doc.analyze.components.iaad." + component;
                        try{
                            clazz = Class.forName(path);
                        }catch (Exception e) {
//                                    code = -1003;
                            msg.append(path + "组件不存在;");
                            log.error(path + "组件不存在");
                        }
                        if (clazz != null && code == 0) {
                            Map map = handler(component, clazz, documentModel,industryType,documentId,jobId);//初始化组件并向组件注入数据
                            code = (int)map.get("code");
                            msg.append(map.get("msg"));
//                            Map webData = getWebData(component,rs, map, fileType, documentId);

                        }
                    }else {
                        code = -1005;
                        msg.append("文件抽取失败");
                    }
                }else {
                    code = -1001;
                    msg.append("参数industryType错误");
                }
            }else{
                code = -1002;
                msg.append(pdfFile.getAbsolutePath() + "文件不存在");
            }
            String endTime = df.format(new Date());
            returnMsg.put("code", code);
            returnMsg.put("msg", msg);
            returnMsg.put("documentId", documentId);
            returnMsg.put("jobId", jobId);
            returnMsg.put("startTime", startTime);
            returnMsg.put("endTime", endTime);
            sendMsg(returnMsg,tag);
        }
        long t2 = System.currentTimeMillis();
        log.info("{}处理消息耗时：{}ms",messageBody,(t2-t1));
        return returnMsg;
    }

    /**
     * @auth 佟媛媛
     * @date 18/11/7 下午3:53
     * @desc 初始化组件并向组件注入数据
     */
    private Map handler(String component,Class clazz,DocumentModel documentModel,String industryType,String documentId,String jobId){
        Map result = new HashMap();
        result.put("code",0);
        try{
            Object obj = ApplicationContextHelper.getBean(component);
            //注入抽取数据
            Method setExtractData = clazz.getMethod("setExtractData", DocumentModel.class);
            setExtractData.invoke(obj, documentModel);
            //查询指标信息
            List<IndustryIndicatorList> industryIndicatorList = getIndustryIndicatorList(industryType,jobId);
            //注入指标信息
            Method setIndustryIndicatorList = clazz.getMethod("setIndustryIndicatorList", List.class);
            setIndustryIndicatorList.invoke(obj, industryIndicatorList);
            //查询评分信息
            IaadGrade iaadGrade = getIaadGrade(documentId,jobId);
            //修改项目名称
            String custName = getCustName(documentModel);
            if(org.apache.commons.lang3.StringUtils.isNotEmpty(custName)){
                Map map = new HashMap();
                map.put("iaadId",iaadGrade.getIaadId());
                map.put("custName",custName);
                integrityRegulationService.updateIaadGradeProjectName(map);
            }
            //注入评分信息
            Method setIaadGrade = clazz.getMethod("setIaadGrade", IaadGrade.class);
            setIaadGrade.invoke(obj, iaadGrade);

            Method handler = clazz.getMethod("handlerIAAD");
            List<IaadIndicatorGradeDetail> list = (List<IaadIndicatorGradeDetail>) handler.invoke(obj);
            result.put("list",list);
            //修改任务状态  如果任务状态为终止中07，则将其改为已终止08，否则改为抽取已完成02
            IaadAnalyzeJob job = integrityRegulationService.getIaadAnalyzeJobById(jobId);
            if(job!=null){
                if("07".equals(job.getStatusCode())){
                    result.put("code",-1006);
                    result.put("msg","任务终止中");
                }else{
                    if(iaadGrade!=null) integrityRegulationService.deleteIaadIndicatorGradeDetail(iaadGrade.getIndicatorGradeId());
                    if(!CollectionUtils.isEmpty(list)) integrityRegulationService.addIaadIndicatorGradeDetail(list);
                    //同步分数
                    if(iaadGrade!=null){
                        Map map = new HashMap();
                        map.put("indicatorGradeId",iaadGrade.getIndicatorGradeId());
                        map.put("matterGradeId",iaadGrade.getMatterGradeId());
                        map.put("iaadId",iaadGrade.getIaadId());
                        map.put("gradeDate",(new Timestamp(Calendar.getInstance().getTime().getTime())).toString());
                        integrityRegulationService.updateIaadIndicatorGradeAutomateTotalScore(map);
                        integrityRegulationService.updateIaadGradeTotalScore(map);
                    }
                }
            }

        }catch (Exception e){
            log.error(e.getMessage(),e);
        }
        return result;
    }


    /**
     * @auth 佟媛媛
     * @date 18/11/25 下午2:24
     * @desc 获取项目民称
     */
    private String getCustName(DocumentModel documentModel){
        String projectName = null;
        KVText kvTextM0 = getKVTextValue(documentModel,"M-0","FXTK","FXR");
        if(kvTextM0!=null){
            projectName = kvTextM0.getText();
        }else{
            KVText kvTextM3 = getKVTextValue(documentModel,"M-3","FXTK","FXR");
            if(kvTextM3!=null){
                projectName = kvTextM3.getText();
            }
        }
        return projectName;
    }

    /**
     * @auth 佟媛媛
     * @date 18/11/8 上午9:56
     * @desc 获取评分信息
     */
    private IaadGrade getIaadGrade(String documentId,String jobId){
        try{
            Map map = new HashMap();
            map.put("documentId",documentId);
            map.put("jobId",jobId);
            return integrityRegulationService.getIaadGrade(map);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return new IaadGrade();
        }
    }

    /**
     * @auth 佟媛媛
     * @date 18/11/7 下午6:32
     * @desc 查询指标信息
     */
    private List<IndustryIndicatorList> getIndustryIndicatorList(String industryType,String jobId){
        try{
            Map map = new HashMap();
            map.put("industryType",industryType);
            map.put("extractType","02");
            if("04".equals(industryType)){//高速公路阈值有执行级别区分
                IaadAnalyzeJob job = integrityRegulationService.getIaadAnalyzeJobById(jobId);
                if(job!=null) map.put("administrativeRanks",job.getAdministrativeRanks());
            }
            return integrityRegulationService.getManualIaadIndicatorGradeDetailList(map);
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return new ArrayList<>();
        }
    }

    /**
     * @auth 佟媛媛
     * @date 18/11/7 下午3:28
     * @desc 获取行业类型
     */
    private IndustryType getIndustryType(String type){
        IndustryType industryType = null;
        switch (type) {
            case "01":
                industryType = IndustryType.CJ;
                break;
            case "02":
                industryType = IndustryType.FDC;
                break;
            case "04":
                industryType = IndustryType.GSGL;
                break;
            case "03":
                industryType = IndustryType.GT;
                break;
            case "05":
                industryType = IndustryType.HD;
                break;
            case "06":
                industryType = IndustryType.MT;
                break;
            case "07":
                industryType = IndustryType.SN;
                break;
        }
        return industryType;
//        return IndustryType.HD;
    }

    /**
     * @auth 佟媛媛
     * @date 18/11/7 下午3:32
     * @desc 向MQ发送消息
     */
    private void sendMsg(JSONObject message, String tag) {
        try {
            Message msg = new Message(topicAnalyzeStatus, tag, message.toJSONString().getBytes("UTF-8"));
            analyzeStatusProducer.send(msg, new SendCallback() {
                @Override
                public void onSuccess(SendResult sendResult) {
                    log.info("生产者向{}[{}]发送消息：{};发送状态：{}" ,topicAnalyzeStatus,tag,message,sendResult.getSendStatus());
                }
                @Override
                public void onException(Throwable e) {
                    log.info("生产者向{}[{}]发送消息：{};发送状态：{}" ,topicAnalyzeStatus,tag,message,"失败");
                    log.error(e.getMessage(), e);
                }
            });
        } catch (Exception e) {
            log.info("生产者向{}[{}]发送消息：{};发送状态：{}" ,topicAnalyzeStatus,tag,message,"失败");
            log.error(e.getMessage(), e);
        }
    }

    /**
     * @auth 佟媛媛
     * @date 18/11/7 下午3:10
     * @desc 分析文本并写入文件
     */
    private DocumentModel analyze(File pdfFile, IndustryType industryType, String documentId) {
        log.info("开始解析文本{},类型:{}", pdfFile.getAbsolutePath(), industryType);
        long t1 = System.currentTimeMillis();
        DocumentModel documentModel = null;
        try{
            String outputPath = docAnalyzeSavePath + File.separator + documentId + File.separator + "doc.analyze.json";
            Gson gson = new GsonBuilder().create();
            PdfParser pdfParser = new PdfParser();
            documentModel = pdfParser.parsePdfOutline(pdfFile, industryType);
//            String content = gson.toJson(documentModell);
//            writeFile(content, outputPath);//结果写入文件
        }catch (Exception e){
            log.error(e.getMessage(),e);
            return null;
        }
        long t2 = System.currentTimeMillis();
        log.info("数据分析存储耗时：{}ms", t2 - t1);
        return documentModel;
    }

    /**
     * @auth 佟媛媛
     * @date 18/11/7 下午3:12
     * @desc 写文件
     */
    private void writeFile(String content, String filePath) {
        try {
            File file = new File(filePath);
            if (!file.getParentFile().exists()) file.getParentFile().mkdirs();
            if (file.exists()) file.delete();
            file.createNewFile();
            FileWriter fileWritter = new FileWriter(file.getAbsoluteFile());
            fileWritter.write(content);
            fileWritter.flush();
            fileWritter.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private KVText getKVTextValue(DocumentModel documentModel,String tableId, String model, String key){
        ChapterModel chapterModel = documentModel.getChapterModel(tableId);
        ExtractBizModel extractBizModel = chapterModel!=null?chapterModel.getModel(model):null;
        if(extractBizModel!=null){
            ExtractItem extractItem = extractBizModel.getExtractItem(key);
            if(extractItem!=null){
                return extractItem.getValue();
            }
        }
        return null;
    }
}
